#include "adc_driver.h"
#include "stm8s_adc2.h"

// -------------------------- 静态全局变量（内部状态管理） --------------------------
// 记录已初始化的通道（支持多通道，用位掩码存储）
static uint8_t s_init_channels = 0;
// 记录当前配置的通道（避免重复配置，优化性能）
static AdcChannel s_current_channel = ADC_CHANNEL_MAX;
// ADC外设初始化标志（多通道共享，仅初始化1次）
static bool s_adc_periph_init = false;

// -------------------------- 静态辅助函数（内部封装，不对外暴露） --------------------------


/**
 * @brief 软件触发ADC转换并等待完成（带超时）
 * @param adc_raw: 指针，用于存储ADC原始值
 * @retval bool: 转换结果（true=成功，false=超时）
 */
static bool adc_trigger_and_wait(AdcChannel channel,uint16_t *adc_raw) {
    if (adc_raw == NULL) {
        return false;
    }

       
    // // 3. 初始化ADC核心参数（单次转换、右对齐、分频适配）
    // ADC2_Init(ADC2_CONVERSIONMODE_CONTINUOUS,  // 单次转换模式（每次read触发1次）
    //         channel,                     // 目标通道
    //         ADC2_PRESSEL_FCPU_D2,        // 分频系数：CPU时钟/2（避免ADC过采样）
    //         ADC2_EXTTRIG_TIM,            // 外部触发源（禁用，用软件触发）
    //         DISABLE,                     // 禁用外部触发
    //         ADC2_ALIGN_RIGHT,            // 数据右对齐（12位值存于低12位）
    //         ADC2_SCHMITTTRIG_ALL,        // 启用施密特触发器（抗干扰）
    //         DISABLE);                    // 禁用中断（简化设计）
    
    // // 4. 重新启用ADC
    // ADC2_Cmd(ENABLE);
 ADC2->CSR &= (uint8_t)(~ADC2_CSR_CH);
  /* Select the ADC2 channel */
  ADC2->CSR |= (uint8_t)(channel);
  ADC2_StartConversion();
    
    // 3. 等待转换完成（带超时）
    uint32_t start_tick = sys_get_tick_ms();
    while (ADC2_GetFlagStatus() == RESET) 
    {
        // 检查超时
        if ((sys_get_tick_ms() - start_tick) >= ADC_CONVERT_TIMEOUT_MS)
         {
            ADC2_ClearFlag();  // 超时后停止转换
            printf("ADC2: Timeout\n");
            return false;
        }
    }
    
    // 4. 读取原始值
    *adc_raw = ADC2_GetConversionValue();
    return true;
}

/**
 * @brief ADC原始值转换为电压（mV，纯整数运算）
 * @param adc_raw: ADC原始值（0~4095）
 * @retval uint16_t: 电压值（单位：mV）
 */
static uint16_t adc_convert_to_voltage(uint16_t adc_raw) {
    // 公式：V(mV) = (adc_raw * 参考电压(mV)) / ADC满量程
    // 用整数运算避免浮点，结果向下取整（满足大多数场景精度需求）
    return (uint16_t)((uint32_t)adc_raw * ADC_REF_VOLTAGE_MV / ADC_RESOLUTION_12BIT);
}

// -------------------------- 对外接口实现 --------------------------
bool adc_init() {
  

    // 2. ADC外设初始化（仅首次调用时执行，多通道共享）
    if (!s_adc_periph_init)
     {  
          ADC2_DeInit();

        ADC2_StartConversion();

        // GPIO_Init(GPIOB,  GPIO_PIN_1, GPIO_MODE_IN_PU_NO_IT);
        // GPIO_Init(GPIOB,  GPIO_PIN_2, GPIO_MODE_IN_PU_NO_IT);
        // GPIO_Init(GPIOB,  GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT);
        // GPIO_Init(GPIOB,  GPIO_PIN_4, GPIO_MODE_IN_PU_NO_IT);
        s_adc_periph_init = true;

        // 3. 初始化ADC核心参数（单次转换、右对齐、分频适配）
        ADC2_Init(ADC2_CONVERSIONMODE_CONTINUOUS,  // 单次转换模式（每次read触发1次）
                ADC2_CHANNEL_0,                     // 目标通道
                ADC2_PRESSEL_FCPU_D2,        // 分频系数：CPU时钟/2（避免ADC过采样）
                ADC2_EXTTRIG_TIM,            // 外部触发源（禁用，用软件触发）
                DISABLE,                     // 禁用外部触发
                ADC2_ALIGN_RIGHT,            // 数据右对齐（12位值存于低12位）
                ADC2_SCHMITTTRIG_ALL,        // 启用施密特触发器（抗干扰）
                DISABLE);                    // 禁用中断（简化设计）
        
        // 4. 重新启用ADC
        ADC2_Cmd(ENABLE);
    }
    

    
  

    

    
    return true;
}

AdcReadStatus adc_read(AdcChannel channel, uint16_t *adc_raw, uint16_t *voltage_mv) {
    // 1. 基础合法性检查
    // if (channel >= ADC_CHANNEL_MAX || !(s_init_channels & (1 << channel))) {
    //     return ADC_READ_ERR_INVALID;  // 通道无效或未初始化
    // }
    
    // 3. 存储原始值（若需要）
    uint16_t raw_val = 0;
    if (adc_raw != NULL || voltage_mv != NULL) {  // 至少需要存储一个值
        if (!adc_trigger_and_wait(channel,&raw_val)) {
            return ADC_READ_ERR_TIMEOUT;  // 转换超时
        }
        if (adc_raw != NULL) {
            *adc_raw = raw_val;
        }
    }
    
    // 4. 转换并存储电压（若需要）
    if (voltage_mv != NULL) {
        *voltage_mv = adc_convert_to_voltage(raw_val);
    }
    
    return ADC_READ_OK;
}